﻿using ABFramework;
using LuaFramework;
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using UIFramework;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using XLua;

public class DebugerManager : MonoBehaviour
{
    #region 实现DebugerManager类的单例
    private static DebugerManager _instance;
    private DebugerManager() { }
    public static DebugerManager Instance
    {
        get
        {
            if (_instance == null)
            {
                GameObject go = new GameObject();
                _instance = go.AddComponent<DebugerManager>();
                go.name = "DebugerManager";
                go.transform.parent = GameInit.GameManager.transform;
            }
            return _instance;
        }
    }
    #endregion

    bool _OpenPanel = false;
    bool _ShowDebug = true;
    bool _ShowStack = false;
    bool _OnlyShowError = false;
    bool _ShowButArrayOne = true;
    int _UseCount1 = 0;
    int _UseCount2 = 0;
    int log_number = 0;

    int _ScreenHeight = Screen.height;
    int _ScreenWidth = Screen.width;
    //显示文本
    string _LogErrorShowType = "只看错误";
    string _LogIsShow = "隐藏日志";
    string _StackIsShow = "显示堆栈";

    //fps计算使用的参数
    float updateInterval = .5f;
    int cnt = 0;
    string stringFps;
    float accum;

    //滚动视图当前滚动的实时位置
    private Vector2 scrollViewVector = Vector2.zero;

    //日志信息保存的sb
    StringBuilder sb_log = new StringBuilder();

    /// <summary>
    /// 初始化
    /// </summary>
    public void Init()
    {
        MonitorLog();
        //Debug.Log("DebugerManager Init!");
    }

    /// <summary>
    /// 添加日志监听
    /// </summary>
    private void MonitorLog()
    {
        Application.logMessageReceived += (string condition, string stackTrace, LogType type) =>
        {
            if (sb_log.Length >= 20001)
            {
                //保存当前最新日志
                SaveDebugLog(sb_log);
                Debug.Log(sb_log.Length);
                sb_log = sb_log.Remove(18000, sb_log.Length - 18000);
            }
            log_number++;
            string dt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            if (type == LogType.Exception || type == LogType.Error)
            {
                sb_log.Insert(0, string.Format("<color=red>错误[{3}]:{0}\n{1}时间 {2}</color>\n\n", condition, stackTrace, dt, log_number));
            }
            else if (!_OnlyShowError)
            {
                if (_ShowStack)
                {
                    sb_log.Insert(0, string.Format("日志[{3}]:{0}\n{1}时间 {2}\n\n", condition, stackTrace, dt, log_number));
                }
                else
                {
                    sb_log.Insert(0, string.Format("日志[{2}]:{0}\n时间 {1}\n\n", condition, dt, log_number));
                }
            }
        };
    }


    /// <summary>
    /// 渲染UI GUI显示核心方法
    /// </summary>
    private void OnGUI()
    {
        //判定是否显示该GUI内容
        if (!_OpenPanel) return;

        SetStyle();
        TopUIShow();

        //判断显示哪个按钮组
        if (_ShowButArrayOne)
        {
            ButtonArrayUIOne();
        }
        else
        {
            ButtonArrayUITwo();
        }

        //Debug日志显示界面
        ShowLogView();
    }
    /// <summary>
    /// 显示日志视图
    /// </summary>
    private void ShowLogView()
    {
        if (!_ShowDebug) return;
        //Debug.Log(Input.mousePosition);
        //鼠标或手指按下设置滚动条位置
        if (Input.GetMouseButton(0) && Input.mousePosition.y > 100 && Input.mousePosition.x > _ScreenWidth / 3 * 2)
        {
            if (Input.mousePosition.y < _ScreenHeight / 2)
            {
                scrollViewVector.y += 20;
                if (scrollViewVector.y >= 4050) scrollViewVector.y = 4050;
            }
            else if (Input.mousePosition.y > _ScreenHeight / 2)
            {
                scrollViewVector.y -= 20;
                if (scrollViewVector.y <= 0) scrollViewVector.y = 0;
            }
        }

        //滚动区域设置
        GUI.skin.box.alignment = TextAnchor.UpperLeft;

        scrollViewVector = GUI.BeginScrollView(new Rect(200, 105, _ScreenWidth - 200, _ScreenHeight - 110), scrollViewVector,
            new Rect(0, 100, _ScreenWidth - 216, 5000), false, false);

        GUI.Label(new Rect(5, 100, _ScreenWidth - 215, 5000), sb_log.ToString(), GUI.skin.box);

        GUI.EndScrollView();


        //清理复制日志按钮
        GUI.skin.label.fontSize = 20;
        if (GUI.Button(new Rect(_ScreenWidth - 140, _ScreenHeight - 50, 55, 33), "复制", GUI.skin.box))
        {
            if (PlatformTool.CopyTextToClipboard(sb_log.ToString())) Debug.Log("复制成功!");
        }
        if (GUI.Button(new Rect(_ScreenWidth - 80, _ScreenHeight - 50, 55, 33), "清空", GUI.skin.box))
        {
            sb_log.Clear();
            scrollViewVector.y = 0;
            Debug.Log("日志清理成功!");
        }
    }
    /// <summary>
    /// 设置UI样式
    /// </summary>
    private void SetStyle()
    {
        // 背景框
        GUI.Box(new Rect(5, 5, 190, _ScreenHeight - 10), "");
        GUI.Box(new Rect(0, 0, _ScreenWidth, _ScreenHeight), "");
        GUI.Box(new Rect(205, 5, _ScreenWidth - 210, 95), "");

        GUI.skin.box.wordWrap = true;
        GUI.skin.box.fontSize = 30;
        GUI.skin.box.alignment = TextAnchor.MiddleCenter;

        GUI.skin.button.fontSize = 30;
        GUI.skin.button.alignment = TextAnchor.MiddleCenter;

        GUI.skin.label.fontSize = 30;
    }

    /// <summary>
    /// 上面的UI显示
    /// </summary>
    private void TopUIShow()
    {
        GUI.Label(new Rect(287, 10, 800, 40), MemoryUsage());
        GUI.Label(new Rect(_ScreenWidth - 140, 10, 140, 40), stringFps);
        GUI.Label(new Rect(287, 55, _ScreenWidth - 210, 40), "UniqueID:" + SystemInfo.deviceUniqueIdentifier);

        GUI.skin.box.fontSize = 23;
        GUI.skin.box.alignment = TextAnchor.MiddleCenter;
        if (GUI.Button(new Rect(210, 13, 70, 33), "[GC]", GUI.skin.box))
        {
            var before = LuaHelper.Instance.GetLuaEnv().Memroy;
            LuaHelper.Instance.GetLuaEnv().FullGc();
            var after = LuaHelper.Instance.GetLuaEnv().Memroy;
            Debug.Log("[GC] Lua Memroy Use! Before:" + before + " KB   After:" + after + " KB");
        }
        if (GUI.Button(new Rect(210, 58, 70, 33), "复制", GUI.skin.box))
        {
            PlatformTool.CopyTextToClipboard(SystemInfo.deviceUniqueIdentifier);
        }
        GUI.skin.button.alignment = TextAnchor.MiddleCenter;

        //日志界面显示
        if (GUI.Button(new Rect(_ScreenWidth - 140, 52, 110, 38), _LogIsShow, GUI.skin.box))
        {
            _ShowDebug = !_ShowDebug;
            if (_ShowDebug)
            {
                _LogIsShow = "隐藏日志";
            }
            else
            {
                _LogIsShow = "显示日志";
            }
        }
        GUI.skin.box.fontSize = 20;
        //复制和清空日志
        if (_ShowDebug)
        {

        }
    }

    /// <summary>
    /// UIButotn组1
    /// </summary>
    private void ButtonArrayUIOne()
    {
        _UseCount1 = 0;
        DoCreateBtn("关闭调试", ref _UseCount1, () =>
        {
            _OpenPanel = !_OpenPanel;
        });
        DoCreateBtn("常用功能", ref _UseCount1, () =>
               {
                   _ShowButArrayOne = false;
               });
        DoCreateBtn("登录窗体", ref _UseCount2, () =>
        {
            LuaHelper.Instance.DoString("ViewManager:OpenPanel(Views.LoginView)");
        });
        DoCreateBtn("监听引用", ref _UseCount1, () =>
        {
            LuaHelper.Instance.DoString("Tool:PrintCSReference()");
        });
        DoCreateBtn("所有引用", ref _UseCount1, () =>
        {
            LuaHelper.Instance.DoString("util.print_func_ref_by_csharp()");
        });
        DoCreateBtn("窗体缓存", ref _UseCount1, () =>
        {
            UIManager.Instance.PrintAllUICacheList();
        });
        DoCreateBtn("其他缓存", ref _UseCount1, () =>
        {
            AssetBundleManager.Instance.GetAllLoadedABNameList();
            LuaHelper.Instance.PrintCacheFileList();
            DTAnimManager.Instance.PrintAllSequenceName();
            ReddotManager.Instance.PrintReddotInfo();
        });
        DoCreateBtn("依赖关系", ref _UseCount1, () =>
        {
            AssetBundleManager.Instance.PrintRelayList();
        });
        DoCreateBtn(_StackIsShow, ref _UseCount1, () =>
        {
            _ShowStack = !_ShowStack;
            if (_ShowStack)
            {
                _StackIsShow = "隐藏堆栈";
            }
            else
            {
                _StackIsShow = "显示堆栈";
            }
        });
        DoCreateBtn(_LogErrorShowType, ref _UseCount1, () =>
        {
            _OnlyShowError = !_OnlyShowError;
            if (_OnlyShowError)
            {
                _LogErrorShowType = "全部日志";
            }
            else
            {
                _LogErrorShowType = "错误日志";
            }
        });
        DoCreateBtn("清理数据", ref _UseCount1, () =>
        {
            PlayerPrefs.DeleteAll();
        });
        DoCreateBtn("清理资源", ref _UseCount1, () =>
        {
            Directory.Delete(PathTools.GetPlatformABRootPath(), true);
            PlayerPrefs.DeleteAll();
            Debug.Log("清理成功！退出app!");
            Application.Quit();
        });
        DoCreateBtn("上传日志", ref _UseCount1, () =>
        {
            //TODO
        });
        DoCreateBtn("重启游戏", ref _UseCount1, () =>
        {
            //删游戏管理器
            Destroy(GameInit.GameManager);
            //删除MainCanvas
            Destroy(UIManager.Instance._UIRootNode.gameObject);
            //释放资源引用
            AssetBundleManager.Instance.UnloadAllLoadedAssetBundles();
            //加载到初始场景
            SceneManager.LoadSceneAsync(0);
        });
        DoCreateBtn("退出游戏", ref _UseCount1, () =>
        {
            Application.Quit();
        });
    }

    /// <summary>
    /// UIButton组2
    /// </summary>
    private void ButtonArrayUITwo()
    {
        _UseCount2 = 0;

        DoCreateBtn("关闭调试", ref _UseCount2, () =>
        {
            _OpenPanel = !_OpenPanel;
        });
        DoCreateBtn("测试功能", ref _UseCount2, () =>
               {
                   _ShowButArrayOne = true;
               });
        DoCreateBtn("打开登录", ref _UseCount2, () =>
        {
            LuaHelper.Instance.DoString("ViewManager:OpenPanel(Views.LoginView)");
        });
        DoCreateBtn("测试No.3", ref _UseCount2, () =>
        {
            //UIMsgManager.Instance.SendUIMssage("Shake", "Shake" + 66);
        });
        DoCreateBtn("红点Ema+", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Email", true);
        });
        DoCreateBtn("红点Not+", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Notice", true);
        });
        DoCreateBtn("红点Ser+", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Service", true);
        });
        DoCreateBtn("红点Rec+", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Record", true);
        });
        DoCreateBtn("红点Not-", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Notice", false);
        });
        DoCreateBtn("红点Ser-", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Service", false);
        });
        DoCreateBtn("红点Ema-", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Email", false);
        });
        DoCreateBtn("红点Rec-", ref _UseCount2, () =>
        {
            ReddotManager.Instance.SetReddotVisible("Record", false);
        });
        DoCreateBtn("测试No.12", ref _UseCount2, () =>
        {
        });
        DoCreateBtn("测试No.13", ref _UseCount2, () =>
        {

        });
        DoCreateBtn("测试No.14", ref _UseCount2, () =>
        {

        });
    }

    /// <summary>
    /// 内存占用
    /// </summary>
    /// <returns></returns>
    string MemoryUsage()
    {
        string lua_memroy = Math.Round(LuaHelper.Instance.GetLuaEnv().Memroy / 1024.0, 2).ToString();
        string unity_memroy = Math.Round(UnityEngine.Profiling.Profiler.usedHeapSizeLong / 1024 / 1024.0, 2).ToString();

        return string.Format("Lua Memery:{0}MB  Unity Memery:{1}MB", lua_memroy, unity_memroy);
    }
    /// <summary>
    /// 创建按钮
    /// </summary>
    /// <param name="title"></param>
    /// <param name="count"></param>
    /// <param name="ac"></param>
    void DoCreateBtn(string title, ref int count, Action ac)
    {
        if (GUI.Button(new Rect(15, 8 + 49 * count, 170, 42), title))
        {
            ac?.Invoke();
        }
        count++;
    }
    private void Update()
    {
        //fps计算
        if (_OpenPanel)
        {
            accum += Time.timeScale / Time.deltaTime; //求平均值
            updateInterval -= Time.deltaTime;
            cnt++;
            if (updateInterval < 0)
            {
                double fps = accum / cnt;
                updateInterval = .5f;
                accum = 0;
                stringFps = "fps:" + Math.Round(fps);
                cnt = 0;
            }
        }

        //切换debug界面显示和隐藏
        if ((Input.GetMouseButtonDown(1) || Input.touchCount == 3))
        {
            _OpenPanel = true;

            //屏蔽UGUI的点击事件
            try
            {
                EventSystem ev = GameObject.Find("EventSystem").GetComponent<EventSystem>();
                ev.enabled = !_OpenPanel;
            }
            catch
            {
                Debug.Log("该场景没有 EventSystem 组件!!!");
            }
        }
    }
    private void OnDestroy()
    {
        //退出前保存app日志
        SaveDebugLog(sb_log);
    }

    /// <summary>
    /// 保存打印日志
    /// </summary>
    void SaveDebugLog(StringBuilder sb)
    {
        string log_path = Application.streamingAssetsPath + "/" + PathTools.DEBUG_LOG_NAME;

        if (!Directory.Exists(Application.streamingAssetsPath)) Directory.CreateDirectory(Application.streamingAssetsPath);

        //将日志文件写入到本地
        using (FileStream fs = new FileStream(log_path, FileMode.Create))
        {
            string str = sb.ToString().Replace("<color=red>", "").Replace("</color>", "");
            byte[] data = Encoding.UTF8.GetBytes(str);
            fs.Write(data, 0, data.Length);
        }
    }
    /// <summary>
    /// 我的debug方法,Lua中不能使用
    /// 可以查看调用者信息
    /// </summary>
    public static void IDebug(string msg, DebugType type = DebugType.Log, [CallerLineNumber] int line = -1, [CallerFilePath] string path = null, [CallerMemberName] string name = null)
    {
        //if (!GameInit.Instance._DebugInfo) return;

        var sp = path.Replace("\\", "/").Split('/');

        msg = msg + "\n调用者信息 >> 类名【" + sp[sp.Length - 1] + "】  方法名【" + name + "】  行号【" + line + "】";

        switch (type)
        {
            case DebugType.Log:
                UnityEngine.Debug.Log(msg);
                break;
            case DebugType.Error:
                UnityEngine.Debug.LogError(msg);
                break;
            case DebugType.Warning:
                UnityEngine.Debug.LogWarning(msg);
                break;
        }
    }
}
